/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Beans;

import Entity.*;
import Entity.RewardVoucher;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author AdminNUS
 */
@Stateless
public class ULPBean implements ULPBeanRemote {

    @PersistenceContext()
    EntityManager em;
    

    public ULPBean() {
    }

    public Integer calculateLoyaltyPoints(Date currentTrans, String customerEmail, Double subtotal) {
        System.out.println(">>> ULP Bean: Calculate loyalty points to be awarded");
        Users accts = new Users();
        int points = 0;
        Query q = em.createQuery("SELECT c from Users c where c.email = :paramCustomerEmail ");
        q.setParameter("paramCustomerEmail", customerEmail);

        accts = (Users) q.getSingleResult();
        if (accts == null) {
            System.out.println(">>> ULP Bean: user not found");
            return 0;
        }
        Double multipler = 0.0;
        accts.getEmail();

        Date recentTrans = accts.getMostRecentTransactionDate();

        boolean isSame = compareMostRecentTransactionDate(recentTrans,currentTrans);
        if (isSame == true) {
            multipler = accts.getCustomerTier().getBonusMultiplier();
        } 
        else {
           multipler = accts.getCustomerTier().getNormalMultiplier();
        }
        
        Double pts = (subtotal * multipler);
        
        points = pts.intValue();

        System.out.println(">>> ULP Bean: " + points + " to be awarded to user: " + customerEmail);

        return points;
    }

    

    public boolean compareMostRecentTransactionDate(Date recentTrans,Date currentTrans) {
       
        SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
        String mostRecentTransactionString = formatter.format(recentTrans);
        
        String currentTransactionString = formatter.format(currentTrans);

        if (mostRecentTransactionString.equals(currentTransactionString)) {
            return true;
        } else 
            return false;
        


       
    }
    /*
     * Method to generate free points and award them to customer
     * This method is called when a customer makes a transaction
     * and the amount of points he earns is computed based on the amount of money he spent.
     */  
    public void awardPoints(long userID, int pointsToAward){
        Users customer = em.find(Users.class, userID);
        int points = customer.getLoyaltypoint() + pointsToAward;
        customer.setLoyaltypoint(points);
        em.flush();
    }
    
    
    //Randall: 15-oct-2011
    public void stakeholderCreateRewardItem(
                 String stakeholder,
                 String reward_Name,
                 String reward_Description,
                 Integer reward_Cost,
                 Integer vouchers_left,
                 boolean unlimitedVouchers
            ){
        
        //System.out.println("************************************** \n" + reward_Description);
        
        char[] temp = reward_Description.toCharArray();

        boolean previousCharIsCarriageReturn = false;
    	String str = "";
    		
    	for(int i=0;i<temp.length;i++){
            int charASCII = temp[i];
            //System.out.println(charASCII + "#");
            
            if(charASCII != 13 && charASCII != 10){
            	str = str + temp[i];
            }
       
            if (previousCharIsCarriageReturn && charASCII == 10){
            	str = str + "\n";
            }
       
            if (charASCII == 13){
            	previousCharIsCarriageReturn = true;
            }else {
            	previousCharIsCarriageReturn = false;
            }       
        }     
        //System.out.println(">>>>>>>>" + str);
        
        
    
        RewardItem reward = new RewardItem(
                  stakeholder,
                  reward_Name,
                  str,
                  reward_Cost,
                  vouchers_left,
                  unlimitedVouchers
            );
        
        em.persist(reward);   
    }
    
    
    //Randall: 15-oct-2011
    public void stakeholderDeleteRewardItem(long rewardItem_id){
        System.out.println(">>> ULPBean: Attempt to delete reward with the ID: " + rewardItem_id);
        RewardItem reward = em.find(RewardItem.class, rewardItem_id);
        
        if (reward == null){
            System.out.println(">>> ULPBean: Attempt to find reward item with ID: " + rewardItem_id + " failed.");
            return;
        }   
        em.remove(reward);
        System.out.println(">>> ULPBean: Delete Success");
    }
    
    
    
    //Randall: 15-oct-2011
    public List<RewardItem> getRewardsByStakeholder(String stakeholderName){
        List<RewardItem> returnList = new ArrayList<RewardItem>();
        
        Query q = em.createQuery("SELECT c from RewardItem c WHERE c.stakeholder = :paramStakeholder");
        q.setParameter("paramStakeholder", stakeholderName);
        
        for(Object o : q.getResultList()){
            RewardItem temp = (RewardItem) o;
            returnList.add(temp);
        }
        
        return returnList;
    }
    
    
    
    //Randall: 15-oct-2011
    //Method called when a user spends points to purchase a reward voucher
    public String buyVoucher(String customerEmail, long rewardItem_id){
        Users customer = findCustomer(customerEmail);
        if(customer == null) return "customer ID not foind";
        
        //*** Find the reward item
        RewardItem reward = em.find(RewardItem.class, rewardItem_id);
        if (reward == null){
            System.out.println(">>> ULPBean: Attempt to find reward item with ID: " + rewardItem_id + " failed.");
            return "reward ID not foind";
        }     
        
        //*** Check if there are still vouchers left
        if(!reward.isUnlimitedVouchers()){
            if(reward.getVouchers_left()<1){
                System.out.println(">>> ULPBean: No vouchers left for this reward");
                return "There are no Vouchers left to purchase for this reward!";
            }
        }    
        
        //*** Check if the user has enough points
        Integer cost = reward.getReward_Cost();
        if(customer.getLoyaltypoint() < cost){
                System.out.println(">>> ULPBean: Customer cannot afford the reward");
                return "Not enough points to purchase this voucher!";
        }
        else{
            RewardVoucher voucher = new RewardVoucher(    
                    reward.getId(),
                    customer.getId(),
                    reward.getStakeholder(),
                    reward.getReward_Name(),
                    reward.getReward_Description(),
                    reward.getReward_Cost(),
                    new Date()
            );
            
            if(!reward.isUnlimitedVouchers()){ //Deduct from the amount of vouchers left open to purchase
                reward.decrementVoucher();
            }
            em.persist(voucher);
            
            //deduct the points cost
            Integer points = customer.getLoyaltypoint() - reward.getReward_Cost();
            customer.setLoyaltypoint(points);
            
            //add the voucher into the user's list of vouchers
            List<RewardVoucher> temp = customer.getList_vouchers();
            temp.add(voucher);
            customer.setList_vouchers(temp);
                    
            
            em.flush();
            return "Voucher successfully purchased!";
        }         
    }
    
    
    //Randall: 15-oct-2011
    //When a customer redeems a voucher, the outlet manager must call this method to set the voucher entity's redeemed boolean to true
    public void redeemVoucher(long voucher_id){
        System.out.println(">>> ULPBean: redeem voucher with the ID: " + voucher_id);
        RewardVoucher voucher = em.find(RewardVoucher.class, voucher_id);
        if (voucher == null) {
            System.out.println(">>> ULPBean: Voucher not found");
            return;
        }
        
        if (voucher.isRedeemed()) {
            System.out.println(">>> ULPBean: Voucher already redeemed");
            return;
        }
        
        voucher.setRedeemed(true);
        System.out.println(">>> ULPBean: Voucher successfully redeemed");
    }
    
    
    
    //Randall: 15-oct-2011
    //This method is called by the customer when he wants to view all of his purchased vouchers.
    public List<RewardVoucher> getVouchersByCustomer(long customerID){
        Query q = em.createQuery("SELECT c FROM RewardVoucher c WHERE c.customer_id = :paramCustomerID"); 
        q.setParameter("paramCustomerID", customerID);
        
        List<RewardVoucher> returnList = new ArrayList<RewardVoucher>();
        for(Object o : q.getResultList()){
            returnList.add( (RewardVoucher)o );
        }
        
        return returnList;
    }
    
    //Randall: 15-oct-2011
    public List<RewardVoucher> getVouchersByCustomerAndStakeholder(long customerID, String stakeholderName){
        Query q = em.createQuery("SELECT c FROM RewardVoucher c WHERE c.stakeholder = :paramStakeholder AND c.customer_id = :paramCustomerID");
        q.setParameter("paramStakeholder", stakeholderName);
        q.setParameter("paramCustomerID", customerID);
        
        List<RewardVoucher> returnList = new ArrayList<RewardVoucher>();
        for(Object o : q.getResultList()){
            returnList.add( (RewardVoucher)o );
        }
        
        return returnList;
    }
    
    
    
    
    
    
    
    //Randall: 15-oct-2011
    private Users findCustomer(String customerEmail){
        Query q = em.createQuery("SELECT c from Users c where c.email = :paramCustomerEmail ");
        q.setParameter("paramCustomerEmail", customerEmail);
        Users customer = (Users)q.getSingleResult();
        if (customer == null){
            System.out.println(">>> ULPBean: Attempt to find customer: " + customerEmail + " failed.");
            return null;
        }
        else return customer;
    }

   
}
